﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Transactions;
using System.Xml;
using System.Xml.Serialization;
using BusinessObjects.Base;

namespace BusinessObjects.Logic.Base {
    public class UnitOfWork<T> : Datalayer.DBBase,IDisposable where T : IEntity, new() {
        #region Privates
        private List<T> _changed = new List<T>();
        private List<T> _new = new List<T>();
        private List<T> _deleted = new List<T>();
        #endregion

        #region Constructor
        protected UnitOfWork(Datalayer.Databases Database) : base(Database) { }
        protected UnitOfWork() {}
        #endregion

        #region Methods
        protected void AddInsertXML(string XML) {
            XmlReader reader = XmlReader.Create(new StringReader(XML));

            XmlSerializer serializer = new XmlSerializer(typeof(T));
            T obj = (T)serializer.Deserialize(reader);

            reader.Close();

            _new.Add(obj);
        }

        protected void AddInsertObjects(IEnumerable<T> Objects) {
            foreach (var obj in Objects) {
                _new.Add(obj);
            }
        }

        protected void AddUpdateObjects(IEnumerable<T> Objects) {
            foreach (var obj in Objects) {
                _changed.Add(obj);
            }
        }

        protected void AddDeleteObjects(IEnumerable<T> Objects) {
            foreach (var obj in Objects) {
                _deleted.Add(obj);
            }
        }

        protected IEnumerable<T> SelectObjects(IEnumerable<T> Objects) {
            return this.Get<T>(Objects);
        }

        protected IEnumerable<T> SelectObjects() {
            return this.Get<T>();
        }

        protected IEnumerable<T> SelectObjects(int ID) {
            return this.Get<T>(ID);
        }

        protected void CommitUnitOfWork() {
            using (TransactionScope scope = new TransactionScope()) {
                if (_changed != null & _changed.Count() >= 1) {
                    this.Update<T>(_changed);
                }

                if (_new != null & _new.Count() >= 1) {
                    this.Insert<T>(_new);
                }

                if (_deleted != null & _deleted.Count() >= 1) {
                    this.Delete<T>(_deleted);
                }

                scope.Complete();
            }
        }
        #endregion

        #region Dispose
        public void Dispose() {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing) {
            if (disposing) {
                if (_changed != null) {
                    _changed = null;
                }
                if (_new != null) {
                    _new = null;
                }
                if (_deleted != null) {
                    _deleted = null;
                }
            }
        }

        ~UnitOfWork() {
            Dispose(false);
        }
        #endregion
    }
}
